/*
** SMSE2K Driver Interface and factory
**
** TODO: actually make this readable
*/

#include <string.h> // need to move this out later!!

// Driver interface (current version), previous versions use different implementations
class IDriver {
	public:
		virtual int Load(const char* fn) = 0;	// Load the file by file name. This should open the filesystem class...
		virtual int Init(CHardware*) = 0; // Initializes the hardware to run a certain subsong (specified by code).
		virtual int GetSubsongCount()  = 0;				// subsong count of the current file
		virtual void SetSubsong(int song) = 0;			// subsong
		virtual void FreeUnusedResources() = 0; // Unloads unused stuff (File handles, etc.)
		virtual void Close() = 0; // Unloads all driver resources and halts playback.
};


// CBaseDriver is the base driver. We avoid using IDriver directly due to interface changes.
class CBaseDriver : public IDriver {

		public:
			virtual int GetSubsongCount()     { return 0; }			// subsong count of the current file
			virtual void SetSubsong(int song) { };					// subsong
};

/****************************************************
		Driver factory stuff. This looks familiar!

Note: there is a flag enabled for some drivers below (it's isTestDriver).
Set this to 1 to prevent users from using the driver except in debug mode.
*****************************************************/
#define DRIVER_INTERFACE_CURRENT_VERSION 1

#define DRIVER_INTERFACE_VERSION_1		 1

#define DRIVER_DOES_NOT_SUPPORT_FILETYPES(class) const char* class##_filetypes[256] = { NULL, };
#define DRIVER_FILETYPE_MAP_START(class) const char* class##_filetypes[256] = {
#define DRIVER_FILETYPE_MAP(ftype)		 ftype,
#define DRIVER_FILETYPE_MAP_END		NULL, };

// driver factory class definition
#define DRIVER_FACTORY(name,description,version,class)\
IDriver* class##_Factory() {\
		return new class;\
}\
CDriverFactory class##factory(name,description,version,class##_Factory,class##_filetypes);

class CDriverFactory;

void RegisterDriverFactory(CDriverFactory* factory);

// DriverFactory just creates a driver by name, which is used almost exclusively by Lua.
IDriver* DriverFactory (const char* name);

// DriverFactory_CreateDriverByExtension creates a driver instance by whatever file extension we gave it.
// Most files go through here.
IDriver* DriverFactory_CreateDriverByExtension(const char* ext);

void OutputDriverList();

typedef IDriver*(*DriverInterfaceConstructor)(); // Constructor call, returns an interface.
typedef IDriver*(*DriverInterfaceInitcall)();	 // This is going to be moved to the above.
typedef void	(*DriverInterfaceOnConstruct)(); // Call this when the class is constructed.

class CDriverFactory {
	private:
		DriverInterfaceInitcall InitCall;
		const char* name;
		const char* description; // what this driver is
		const char** supportedfiletypes; // class 'CDriverFactory' has an illegal zero-sized array
		int interfaceversion;
		int isTestDriver;

	public:

		CDriverFactory(const char* name, const char* description, int intf_version, DriverInterfaceInitcall initcall, const char** ftypelist) {
				this->name = name;
				this->description = description;
				this->interfaceversion = intf_version;
				this->InitCall = initcall;
				this->supportedfiletypes = ftypelist;

				RegisterDriverFactory(this);
		}

		const char* GetName() { return this->name; }
		const char* GetDescription() { return this->description; }

		int SupportsFileType(const char* extention) {
			int i = 0;
			while (supportedfiletypes[i] != NULL) {
				Msg("SFT: %s\n",extention);
				if (!strcmpi(supportedfiletypes[i],extention))
					return 1;
				i++;
			}

			return 0;
		}

		int IsTestDriver() { return this->isTestDriver; }
		int GetInterfaceVersion() { return this->interfaceversion; }
		
		IDriver* Init() { return InitCall(); }
};

